# -*- coding: utf-8 -*-

import sys
import time
import re

from selenium import selenium

import sumc
from sumc.data import DBHelper

seleniumHost = 'localhost'
seleniumPort = str(4444)
#browserStartCommand = "/usr/bin/firefox-remote"
browserStartCommand = "*firefox"
browserURL = "http://gps.skgt-bg.com"

class SiteSpider(object):
    
    loc_type = '//select[@id="ctl00_ContentPlaceHolder1_ddlTransportType"]'
    loc_tine = '//select[@id="ctl00_ContentPlaceHolder1_ddlLines"]'
    loc_stop = '//select[@id="ctl00_ContentPlaceHolder1_ddlStops"]'
    id_forward = 'ctl00_ContentPlaceHolder1_rblRoute_0'
    id_backward = 'ctl00_ContentPlaceHolder1_rblRoute_1'
    id_result = 'ctl00_ContentPlaceHolder1_gvTimes_ctl%02d_lblTime'

    script_waitForLines = "selenium.browserbot.getCurrentWindow().document." \
        "getElementById('ctl00_ContentPlaceHolder1_ddlLines').options.length > 1"
    script_waitForStops = "selenium.browserbot.getCurrentWindow().document." \
        "getElementById('ctl00_ContentPlaceHolder1_ddlStops').options.length > 1"
    script_waitForDirection = "selenium.browserbot.getCurrentWindow()." \
        "document.getElementById('%s')" # requires parameter
    scriptWaitForResult = "selenium.browserbot.getCurrentWindow().document." \
        "getElementById('ctl00_ContentPlaceHolder1_gvTimes_ctl02_lblTime')" #ctl00_ContentPlaceHolder1_gvTimes_ctl02_lblTime
        
    re_result = re.compile(r'([0-9]{2}:[0-9]{2}) изчислено в: (.*?)$')
    
    def __init__(self, seleniumHost=seleniumHost, seleniumPort=seleniumPort, 
                 browserStartCommand=browserStartCommand, browserURL=browserURL):
        
        self.selenium = selenium(seleniumHost, seleniumPort, browserStartCommand, browserURL)
        self.selenium.start()
        self.selenium.allow_native_xpath(True)

    def getTransportTypes(self):
        s = self.selenium
        s.open('/Web/SelectByLine.aspx')
        transportTypes = s.get_select_options(self.loc_type)
        transportTypes.remove(u'-- Избери --')
        return transportTypes
    
    def getTransportLines(self, transportType):
        s = self.selenium
        s.open('/Web/SelectByLine.aspx')
        s.select(self.loc_type, transportType)
        s.wait_for_condition(self.script_waitForLines, 10000);
        transportLines = s.get_select_options(self.loc_tine)
        transportLines.remove(u'-- Избери --')
        return transportLines
    
    def getStops(self, transportType, lineLabel, direction = sumc.FORWARD):
        s = self.selenium
        s.open('/Web/SelectByLine.aspx')
        s.select(self.loc_type, transportType)
        s.wait_for_condition(self.script_waitForLines, 10000);
        
        if direction == sumc.FORWARD or direction == sumc.BOTH:
            id_dir = self.id_forward
        else:
            id_dir = self.id_backward
        
        s.select(self.loc_tine, lineLabel)
        s.wait_for_condition(self.script_waitForDirection % (id_dir, ), 10000)
        
        s.click("id="+id_dir)
        s.wait_for_condition(self.script_waitForStops, 10000)
            
        stops = s.get_select_options(self.loc_stop)
        stops.remove(u'-- Избери --')
        
        if direction == sumc.BOTH:
            s.click("id="+self.id_backward)
            time.sleep(2)
            s.wait_for_condition(self.script_waitForStops, 10000)
            stopsBackward = s.get_select_options(self.loc_stop)
            stopsBackward.remove(u'-- Избери --')
            
            return (stops, stopsBackward)
        
        return stops
        
    def getArrivalTimes(self, transportType, lineLabel, direction, stopLabel):
        s = self.selenium
        s.open('/Web/SelectByLine.aspx')
        s.select(self.loc_type, transportType)
        s.wait_for_condition(self.script_waitForLines, 10000);

        if direction == sumc.FORWARD:
            id_dir = self.id_forward
        else:
            id_dir = self.id_backward
        
        s.select(self.loc_tine, lineLabel)
        s.wait_for_condition(self.script_waitForDirection % (id_dir, ), 10000)
        
        s.click("id="+id_dir)
        s.wait_for_condition(self.script_waitForStops, 10000)
        
        s.select(self.loc_stop, stopLabel)
        s.wait_for_condition(self.scriptWaitForResult, 10000)

        result = {
            'calculated' : None,
            'arrivals' : [],
        }
        for i in xrange(2, 20):
            spanId = self.id_result % (i, )
            spanLocator = "id="+spanId
            if not s.is_element_present(spanLocator):
                return result
            
            txt = s.get_text(spanLocator)
            m = self.re_result.match(txt.encode('utf-8'))
            if m and not result['calculated']:
                result['calculated'] = m.group(2)
            if m:
                result['arrivals'].append(m.group(1))
            
        return result

        
    def __del__(self):
        self.selenium.stop()
        
        
class Harvester(object):
    
    def __init__(self, dbHelper, spider):
        self.db = dbHelper
        self.s = spider
        
        self.currentTypeId = None
        self.currentTypeLabel = None
        self.currentLineId = None
        self.currentLineLabel = None
        
    
    def harvest(self):
        db = self.db
        db.createDatabase()
        
        ttLabels = self.s.getTransportTypes()
        
        transportTypes = {}
        for ttype in ttLabels:
            id = db.addTransportType(ttype)
            transportTypes[id] = ttype
        
        for (typeId, typeLabel) in transportTypes.iteritems():
            self._harvestLines(typeId, typeLabel)


    def _harvestLines(self, typeId, typeLabel):
        self.currentTypeId = typeId
        self.currentTypeLabel = typeLabel
        
        lineLabels = self.s.getTransportLines(typeLabel)
        
        transportLines = {}
        for llabel in lineLabels:
            id = self.db.addTransportLine(typeId, llabel)
            transportLines[id] = llabel
        
        for (lineId, lineLabel) in transportLines.iteritems():
            self._harvestStops(lineId, lineLabel, sumc.FORWARD)
            self._harvestStops(lineId, lineLabel, sumc.BACKWARD)

    def _harvestStops(self, lineId, lineLabel, direction):
        self.currentLineId = lineId
        self.currentLineLabel = lineLabel
        
        stopLabels = self.s.getStops(self.currentTypeLabel, lineLabel, direction)
        
        stopIds = []
        for stopLabel in stopLabels:
            stopNumber = sumc.getStopNumberFromLabel(stopLabel)
            if not self.db.hasStopNumber(stopNumber):
                id = self.db.addStop(stopLabel)
            else:
                id = self.db.getStopIdByNumber(stopNumber)
            
            stopIds.append(id)
            
        for stopId in stopIds:
            self.db.addLineStopLink(lineId, stopId, direction)


if __name__ == '__main__':
    spider = SiteSpider()
    res = spider.getArrivalTimes(u'Автобусен', '94', sumc.BACKWARD, u'(1609) СК НА НСА')
    print res